home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / njsort11.arc / COMPARES.ASM next >
Assembly Source File  |  1989-01-02  |  14KB  |  751 lines

  1.  
  2. ;   Nifty James' Famous Sort Tool
  3. ;    assembly language support module
  4. ;   Copyright 1988 by Mike Blaszczak
  5. ;   Version 1.00 of 08 May 1988
  6. ;   Version 1.05 of 19 May 1988
  7. ;   Version 1.10 of 03 July 1988
  8. ; for Microsoft Macro Assembler Version 5.10/DOS
  9.  
  10. ;   This module provides fast compare routines for the main .C module.
  11.  
  12. ;   Four compare routines are provided:
  13.  
  14. ;    comp_0
  15. ;   Compare the two strings, paying attention only to reversed sort order.
  16.  
  17. ;    comp_1
  18. ;   Compare the two strings, paying attention only to reversed sort order
  19. ;   and case insensitivity.
  20.  
  21. ;    comp_2
  22. ;   Compare the two strings, paying attention to case insensitivity,
  23. ;   whitespace skipping, and reversed sort order.
  24.  
  25. ;    comp_3
  26. ;   Compare the two strings, paying attention to case insnesitivity,
  27. ;   whitespace skipping, reversed sort order, and sort key fields or
  28. ;   columns.
  29.  
  30. ;    comp_bin
  31. ;   Compare the two strings, treating them as binary data strings.
  32. ;   This compare is affected by order, only.  The compares are limited
  33. ;   in length only by their size -- there is no terminating character.
  34.  
  35.  
  36. ;   One support routine is provided:
  37.  
  38. ;    checkblank
  39. ;   Determines if the passed string is a blank line.  Returns 0
  40. ;   if it is not a blank line or if skipblanks is not set.  Returns 1
  41. ;   if skipblanks is set and the line is empty or contains only
  42. ;   whitespace.
  43.  
  44. ;   all comp_x routines accept two pointers to strings
  45. ;   all comp_xp routines accept two pointers to pointers to strings
  46. ;   checkblank accepts a pointer to a string
  47. ;   all routines return a signed integer
  48.  
  49. ;   THIS MODULE IS HARDCODED FOR USE WITH THE COMPACT MODEL.
  50.  
  51. tab    equ    9
  52. space    equ    32
  53.  
  54.     .model    compact,C
  55.     .data
  56.  
  57.     extrn    seper:byte
  58.     extrn    reversed:byte
  59.     extrn    ignorewhite:byte
  60.     extrn    firstkey:word
  61.     extrn    firstlen:word
  62.     extrn    secondkey:word
  63.     extrn    secondlen:word
  64.     extrn    thirdkey:word
  65.     extrn    thirdlen:word
  66.     extrn    fourthkey:word
  67.     extrn    fourthlen:word
  68.     extrn    fifthkey:word
  69.     extrn    fifthlen:word
  70.     extrn    blastdupes:byte
  71.     extrn    insensitive:byte
  72.     extrn    skipblanks:byte
  73.     extrn    columns:byte
  74.     extrn    recwidth:word
  75.  
  76. compcalls    label    dword
  77. compcallslo    dw    0
  78. compcallshi    dw    0
  79.  
  80.     public    compcalls
  81.  
  82. ; ---------------------------------------------------------------------------
  83.  
  84.     .code
  85.  
  86.     extrn    strcmp:near
  87.     extrn    stricmp:near
  88.     extrn    strncmp:near
  89.     extrn    strnicmp:near
  90.     extrn    strlen:near
  91.     extrn    memcmp:near
  92.  
  93.     public    comp_0x
  94.     public    comp_1x
  95.  
  96.  
  97.  
  98.     public delcmp        ; these are not really public, but
  99.                 ; this makes it visibile to CodeView
  100.     public inccalls
  101.     public    colcmp
  102.     public    domemcmp
  103.         
  104. ; ---------------------------------------------------------------------------
  105.  
  106. comp_gen    proc
  107.  
  108.     assume    ds:nothing
  109.  
  110.     mov    ax,recwidth    ; is there a recwwidth?
  111.     and    ax,ax
  112.     je    comp_2        ; nope, use comp_2
  113. comp_gen2:    jmp    comp_bin    ; yes,  use comp_bin
  114.  
  115. comp_gen    endp
  116.  
  117. ; ---------------------------------------------------------------------------
  118. comp_0x:    call    inccalls
  119.  
  120. comp_0    proc
  121.  
  122.     push    bp
  123.     mov    bp,sp            ; setup addressing
  124.  
  125.     mov    ax,[bp+4]        ;first offset
  126.     mov    bx,[bp+6]        ;first segment
  127.     mov    cx,[bp+8]        ;second offset
  128.     mov    dx,[bp+10]        ;second segment
  129.  
  130.     assume    ds:nothing
  131.     cmp    reversed,0        ; are we reversed?
  132.     assume ds:_DATA
  133.     je    _comp_0_nr
  134.  
  135.     xchg    ax,cx
  136.     xchg    bx,dx            ; yes!  swap pointers around
  137.  
  138. _comp_0_nr:
  139.     push    dx            ; push everything in order
  140.     push    cx
  141.     push    bx
  142.     push    ax
  143.     assume    ds:nothing
  144.     call    strcmp            ; it's the fastest!
  145.     assume ds:_DATA
  146.  
  147.     mov    sp,bp              ; restore registers
  148.     pop    bp
  149.     ret                ; and return
  150.  
  151. comp_0    endp
  152.  
  153. ; ---------------------------------------------------------------------------
  154.  
  155. comp_1x:    call    inccalls
  156.  
  157. comp_1    proc
  158.  
  159.     push    bp
  160.     mov    bp,sp            ; setup addressing
  161.  
  162.     mov    ax,[bp+4]        ;first offset
  163.     mov    bx,[bp+6]        ;first segment
  164.     mov    cx,[bp+8]        ;second offset
  165.     mov    dx,[bp+10]        ;second segment
  166.  
  167.     assume    ds:nothing
  168.     cmp    reversed,0        ; are we reversed?
  169.     je    _comp_1_nr
  170.     assume    ds:_DATA
  171.  
  172.     xchg    ax,cx
  173.     xchg    bx,dx            ; yes!  swap pointers around
  174.  
  175. _comp_1_nr:
  176.     push    dx            ; push everything in order
  177.     push    cx
  178.     push    bx
  179.     push    ax
  180.  
  181.     assume    ds:nothing
  182.     cmp    insensitive,0
  183.     assume ds:_DATA
  184.     jne    _comp_1_ci
  185.     call    strcmp            ; it's the fastest!
  186.     jmp    short _comp_1_re
  187.  
  188. _comp_1_ci:    call    stricmp
  189.     
  190. _comp_1_re:
  191.     mov    sp,bp            ; restore registers
  192.     pop    bp
  193.     ret                ; and return
  194.  
  195. comp_1    endp
  196.  
  197. ; ---------------------------------------------------------------------------
  198.  
  199. comp_2    proc
  200.  
  201.     push    bp
  202.     mov    bp,sp            ; setup addressing
  203.     push    ds            ; save the important regs
  204.     push    si
  205.     push    di
  206.  
  207.     mov    al,ignorewhite        ; get the flag now
  208.  
  209.     lds    si,[bp+04]        ; DS:SI --> first
  210.     dec    si
  211.     les    di,[bp+08]        ; ES:DI --> second
  212.     dec    di
  213.  
  214.     and    al,al            ; is it set?
  215.     je    _comp_2jc        ; nope, just call it
  216.  
  217.     ; skip whitespcae on first
  218.  
  219. _comp_21up:    inc    si
  220.     mov    al,[si]
  221.     cmp    al,space
  222.     je    _comp_21up        ; skip the space
  223.     cmp    al,tab
  224.     je    _comp_21up        ; or the tab
  225.  
  226.     ; skip whiespace on second
  227.  
  228. _comp_22up:    inc    di
  229.     mov    al,es:[di]
  230.     cmp    al,space        ; skip the space
  231.     je    _comp_22up
  232.     cmp    al,tab
  233.     je    _comp_22up
  234.  
  235.     ; push the pointers and call!
  236.  
  237. _comp_2jc:
  238.     push    es
  239.     push    di
  240.     push    ds
  241.     push    si
  242.     call    comp_1            ; call next level down
  243.     add    sp,8            ; discard stack data
  244.  
  245.     pop    di
  246.     pop    si
  247.     pop    ds
  248.     mov    sp,bp            ; restore registers
  249.     pop    bp
  250.     ret                ; and return
  251.  
  252. comp_2    endp
  253.  
  254. ; ---------------------------------------------------------------------------
  255.  
  256. comp_3    proc
  257.  
  258.     push    bp
  259.     mov    bp,sp            ; setup addressing
  260.     push    ds            ; save the important regs
  261.     push    si
  262.     push    di
  263.  
  264.     assume    ds:nothing
  265.     mov    al,ignorewhite        ; get the flag now
  266.     mov    ah,reversed
  267.  
  268.     lds    si,[bp+04]        ; DS:SI --> first
  269.     les    di,[bp+08]        ; ES:DI --> second
  270.  
  271.     and    ah,ah            ; is it reversed?
  272.     jne    _comp_3nr        ; nope, no need to reverse
  273.  
  274.     xchg    si,di            ; yes, flip pointers
  275.     push    es
  276.     push    ds
  277.     pop    es
  278.     pop    ds            ; around
  279.  
  280. _comp_3nr:
  281.     and    al,al            ; is it set?
  282.     je    _comp_3jc        ; nope, just call it
  283.     dec    si            ; downadjust pointers
  284.     dec    di
  285.  
  286.     ; skip whitespcae on first
  287.  
  288. _comp_31up:    inc    si
  289.     mov    al,[si]
  290.     cmp    al,space
  291.     je    _comp_31up        ; skip the space
  292.     cmp    al,tab
  293.     je    _comp_31up        ; or the tab
  294.  
  295.     ; skip whiespace on second
  296.  
  297. _comp_32up:    inc    di
  298.     mov    al,es:[di]
  299.     cmp    al,space        ; skip the space
  300.     je    _comp_32up
  301.     cmp    al,tab
  302.     je    _comp_32up
  303.  
  304.     ; push the pointers and call!
  305.  
  306. _comp_3jc:
  307.     mov    ax,firstkey
  308.     mov    bx,firstlen
  309.     push    bx
  310.     push    ax
  311.     push    ds
  312.     push    si
  313.     push    es
  314.     push    di
  315.     call    delcmp
  316.     add    sp,12
  317.     and    ax,ax
  318.     jne    _comp_3end
  319.  
  320.     mov    ax,secondkey
  321.     and    ax,ax
  322.     je    _comp_3end
  323.     call    inccalls
  324.     mov    bx,secondlen
  325.     push    bx
  326.     push    ax
  327.     push    ds
  328.     push    si
  329.     push    es
  330.     push    di
  331.     call    delcmp
  332.     add    sp,12
  333.     and    ax,ax
  334.     jne    _comp_3end
  335.  
  336.     mov    ax,thirdkey
  337.     and    ax,ax
  338.     je    _comp_3end
  339.     call    inccalls
  340.     mov    bx,thirdlen
  341.     push    bx
  342.     push    ax
  343.     push    ds
  344.     push    si
  345.     push    es
  346.     push    di
  347.     call    delcmp
  348.     add    sp,12
  349.     and    ax,ax
  350.     jne    _comp_3end
  351.  
  352.     mov    ax,fourthkey
  353.     and    ax,ax
  354.     je    _comp_3end
  355.     call    inccalls
  356.     mov    bx,fourthlen
  357.     push    bx
  358.     push    ax
  359.     push    ds
  360.     push    si
  361.     push    es
  362.     push    di
  363.     call    delcmp
  364.     add    sp,12
  365.     and    ax,ax
  366.     jne    _comp_3end
  367.  
  368.     mov    ax,fifthkey
  369.     and    ax,ax
  370.     je    _comp_3end
  371.     call    inccalls
  372.     mov    bx,fifthlen
  373.     push    bx
  374.     push    ax
  375.     push    ds
  376.     push    si
  377.     push    es
  378.     push    di
  379.     call    delcmp
  380.     add    sp,12
  381.  
  382. _comp_3end:    pop    di
  383.     pop    si
  384.     pop    ds
  385.     assume    ds:_DATA
  386.     mov    sp,bp            ; restore registers
  387.     pop    bp
  388.     ret                ; and return
  389.  
  390. comp_3    endp
  391.  
  392. ; ---------------------------------------------------------------------------
  393.  
  394. comp_bin    proc
  395.     assume    ds:_DATA
  396.  
  397.     call    inccalls
  398.  
  399.     push    bp
  400.     mov    bp,sp            ; setup addressing
  401.     push    ds            ; save the important regs
  402.     push    si
  403.     push    di
  404.  
  405.     assume    ds:nothing
  406.     mov    al,reversed
  407.  
  408.     lds    si,[bp+04]        ; DS:SI --> first
  409.     les    di,[bp+08]        ; ES:DI --> second
  410.  
  411.     and    al,al            ; is it reversed?
  412.     jne    _comp_binnr        ; nope, no need to reverse
  413.  
  414.     xchg    si,di            ; yes, flip pointers
  415.     push    es
  416.     push    ds
  417.     pop    es
  418.     pop    ds            ; around
  419.  
  420. _comp_binnr:
  421.     mov    ax,firstkey
  422.     mov    bx,firstlen        ; get the first key
  423.     call    domemcmp
  424.     and    ax,ax            ; is it equal?
  425.     jne    _comp_binend        ; yes, we can exit
  426.  
  427.     mov    ax,secondkey
  428.     and    ax,ax            ; compare by second key
  429.     je    _comp_binend        ; if it exists
  430.  
  431.     mov    bx,secondlen
  432.     call    domemcmp
  433.     and    ax,ax
  434.     jne    _comp_binend
  435.  
  436.     mov    ax,thirdkey
  437.     and    ax,ax
  438.     je    _comp_binend
  439.  
  440.     mov    ax,thirdkey
  441.     and    ax,ax
  442.     je    _comp_binend
  443.  
  444.     mov    bx,thirdlen
  445.     call    domemcmp
  446.     and    ax,ax
  447.     jne    _comp_binend
  448.  
  449.     mov    ax,fourthkey
  450.     and    ax,ax
  451.     je    _comp_binend
  452.  
  453.     mov    bx,fourthlen
  454.     call    domemcmp
  455.     and    ax,ax
  456.     jne    _comp_binend
  457.  
  458.     mov    ax,fifthkey
  459.     and    ax,ax
  460.     je    _comp_binend
  461.  
  462.     mov    bx,fifthlen
  463.     call    domemcmp
  464.  
  465. _comp_binend:    pop    di
  466.     pop    si
  467.     pop    ds
  468.     assume    ds:_DATA
  469.     mov    sp,bp            ; restore registers
  470.     pop    bp
  471.     ret                ; and return
  472.  
  473. comp_bin    endp
  474.  
  475. ; ---------------------------------------------------------------------------
  476.  
  477. domemcmp    proc
  478.  
  479.     push    bx
  480.     push    si
  481.     push    di            ; save the regs
  482.  
  483.     add    si,ax
  484.     add    di,ax            ; change the pointers to
  485.                     ; the beginning of the key
  486.  
  487.     push    bx            ; push the length
  488.     push    ds
  489.     push    si
  490.     push    es
  491.     push    di            ; push operands
  492.     call    memcmp            ; compare the ranges!
  493.     add    sp,10            ; remove operands
  494.  
  495.     pop    di            ; restore registers
  496.     pop    si
  497.     pop    bx
  498.     ret
  499.  
  500. domemcmp    endp
  501.  
  502. ; ---------------------------------------------------------------------------
  503.  
  504. delcmp    proc
  505.     assume    ds:nothing
  506.  
  507.     push    bp
  508.     mov    bp,sp            ; setup addressing
  509.     push    ds            ; save the important regs
  510.     push    es
  511.     push    si
  512.     push    di
  513.  
  514. delcmp2:    mov    bl,seper        ; put the delimiter in a
  515.                     ;   safe place
  516.     mov    bh,insensitive        ; remember the /C flag
  517.  
  518.     lds    si,[bp+4]        ; DS:SI --> first
  519.     dec    si
  520.     les    di,[bp+8]        ; ES:DI --> second
  521.     dec    di
  522.     mov    ax,[bp+12]        ; AX = delimiter number
  523.  
  524.     assume    ds:nothing
  525.  
  526.     cmp    columns,0        ; columns are a bit different
  527.     jne    colcmp
  528.  
  529.     mov    ah,al            ; AH = AL = delim number
  530.  
  531. delcmp_gd1:    dec    ah
  532.     jz    delcmp_gd2
  533. delcmp_gd1c:    inc    si
  534.     cmp    [si],bl            ; try to find a delimiter
  535.     jne    delcmp_gd1c        ; to get started
  536.     je    delcmp_gd1
  537.  
  538. delcmp_gd2:    dec    al
  539.     jz    delcmp_l
  540. delcmp_gd2c:    inc    di
  541.     cmp    es:[di],bl
  542.     jne    delcmp_gd2c
  543.     je    delcmp_gd2
  544.  
  545. delcmp_l:    inc    si            ; compare next characters
  546.     inc    di
  547.     mov    ah,es:[di]        ; get characters
  548.     mov    al,[si]
  549.  
  550.     cmp    ah,al            ; are they equal right now?
  551.     jne    delcmp_tc
  552.  
  553. delcmp_cd:    cmp    al,bl            ; they're equal!  is it delim?
  554.     je    delcmp_eq        ; yes, exit with a zero
  555.     and    al,al            ; is it '\0'?
  556.     jne    delcmp_l        ; nope, keep going
  557.  
  558. delcmp_eq:    xor    ax,ax            ; return a zero!
  559.     jmp    short delcmp_out
  560.  
  561. delcmp_tc:    and    bh,bh            ; is it /C?
  562.     je    delcmp_ma        ;  nope, just split!
  563.  
  564.     xchg    ah,al
  565.     sub    al,'A'            ; knock the char out of alpha
  566.     cmp    al,'Z'-'A'+1        ; is it uppercase?
  567.     sbb    cl,cl            ; CL = FF if it is
  568.     and    cl,'a'-'A'        ; CL = 20 if it is
  569.     add    al,cl            ; now it's lowercase
  570.     add    al,'A'            ; now it's alpha again!
  571.     xchg    ah,al            ; do it again
  572.     sub    al,'A'            ;  for the other char
  573.     cmp    al,'Z'-'A'+1
  574.     sbb    cl,cl    
  575.     and    cl,'a'-'A'
  576.     add    al,cl    
  577.     add    al,'A'    
  578.  
  579.     cmp    al,ah            ; are they equal now?
  580.     jne    delcmp_ma        ;  nope, not equal, were out
  581.  
  582. delcmp_cdo:                    ; ...unless there was a delimiter
  583.     cmp    al,bl            ; is this one a delimiter?
  584.     je    delcmp_ma        ;  yes, find the answer
  585.     cmp    ah,bl            ; is this one a delimiter?
  586.     je    delcmp_ma        ;  yeah, use that
  587.     and    ah,ah            ; how about '\0'?
  588.     je    delcmp_ma        ;  banzai!
  589.     and    al,al            ; well, last shot
  590.     jne    delcmp_l        ; nope, go back and try again
  591.  
  592. delcmp_ma:    ; subtract one from the other to get an answer
  593.     ; if first>second, +
  594.     ; if first<second, -
  595.  
  596.     xor    bx,bx
  597.     mov    bl,ah
  598.     mov    ah,0            ; AX = <AL>,  BX = <AH>
  599.     sub    ax,bx            ; that's our answer!
  600.  
  601. delcmp_out:    pop    di           
  602.     pop    si
  603.     pop    es
  604.     pop    ds
  605.     mov    sp,bp            ; restore registers
  606.     pop    bp
  607.     ret                ; and return to caller
  608.  
  609.     assume    ds:_DATA
  610. delcmp    endp
  611.  
  612. ; ---------------------------------------------------------------------------
  613.  
  614. colcmp    proc
  615.  
  616.     mov    bl,insensitive        ; remember the /C flag
  617.     mov    bh,ignorewhite        ; and the /I flag
  618.     
  619.     lds    si,[bp+4]        ; DS:SI --> first
  620.     dec    si
  621.     les    di,[bp+8]        ; ES:DI --> second
  622.     dec    di
  623.     mov    ax,[bp+12]        ; AX = delimiter number
  624.  
  625.     assume    ds:nothing
  626.  
  627.     mov    dx,firstkey
  628.     cmp    ax,1
  629.     jne    colcmpit
  630.  
  631.     mov    dx,secondkey
  632.     cmp    ax,2
  633.     jne    colcmpit
  634.  
  635.     mov    dx,thirdkey
  636.     cmp    ax,3
  637.     jne    colcmpit
  638.  
  639.     mov    dx,fourthkey
  640.     cmp    ax,4
  641.     jne    colcmpit
  642.  
  643.     mov    dx,fifthkey
  644.  
  645. colcmpit:    add    di,dx
  646.     add    si,dx
  647.  
  648.     and    bh,bh
  649.     je    colcmpnsws
  650.  
  651.     dec    si
  652. colcmpss:    inc    si
  653.     mov    al,[si]
  654.     cmp    al,space
  655.     je    colcmpss
  656.     cmp    al,tab
  657.     je    colcmpss
  658.  
  659.     dec    di
  660. colcmpsd:    inc    di
  661.     mov    al,[di]
  662.     cmp    al,space
  663.     je    colcmpsd
  664.     cmp    al,tab
  665.     je    colcmpsd
  666.  
  667. colcmpnsws:    mov    dx,[bp+14]    ; get length
  668.  
  669.     push    dx
  670.     push    es
  671.     push    di
  672.     push    ds
  673.     push    si
  674.  
  675.     and    bl,bl            ; should we ignore case?
  676.     jne    colcmp_ni        ;  yes! call strnicmp()
  677.  
  678. colcmp_n:    call    strncmp
  679.     add    sp,6
  680.     jmp    short    colcmp_out
  681.  
  682. colcmp_ni:    call    strnicmp
  683.     add    sp,6
  684.     jmp    short    colcmp_out
  685.  
  686. colcmp_out:    pop    di           
  687.     pop    si
  688.     pop    es
  689.     pop    ds
  690.     mov    sp,bp            ; restore registers
  691.     pop    bp
  692.     ret                ; and return to caller
  693.  
  694. colcmp    endp
  695.  
  696. ; ---------------------------------------------------------------------------
  697.  
  698. checkblank    proc
  699.  
  700.     cmp    skipblanks,0        ;is flag set?
  701.     jne    _cbdo            ;yes, do the work
  702.  
  703.     xor    ax,ax            ;otherwise, return with 0
  704.     ret
  705.  
  706. _cbdo:    push    bp            ; setup addressing
  707.     mov    bp,sp
  708.     push    si
  709.     push    ds
  710.  
  711.     lds    si,[bp+4]        ; get pointer
  712.  
  713. _cbwork:    lodsb            ; get next character
  714.     cmp    al,space
  715.     je    _cbwork
  716.     cmp    al,tab
  717.     je    _cbwork        ; if its white, keep looping
  718.     cmp    al,0         ; if it's EOS, answer is 1!
  719.     je    _cbyes    
  720.  
  721.     xor    ax,ax        ; otherwise, answer is 0
  722.     jmp    short _cbend
  723.  
  724. _cbyes:    mov    ax,1
  725.  
  726. _cbend:    pop    ds        ; restore regs and split
  727.     pop    si
  728.     mov    sp,bp
  729.     pop    bp
  730.     ret
  731.  
  732. checkblank    endp
  733.  
  734. ; ---------------------------------------------------------------------------
  735.  
  736. inccalls    proc
  737.     assume ds:nothing
  738.  
  739.     inc    compcallslo        ; increment _compcalls by 1
  740.     jne    inccalls2
  741.  
  742.     inc    compcallshi
  743.  
  744. inccalls2:    ret
  745.     assume    ds:_DATA
  746. inccalls    endp
  747.  
  748.     end
  749.  
  750.  
  751.